package com.ruoyi.user.service.thirdpay.wx;

import com.alibaba.fastjson.JSON;
import com.ruoyi.user.domain.UserOrder;
import com.ruoyi.user.service.thirdpay.AbstractPayService;
import com.ruoyi.user.service.thirdpay.wx.model.JgrmSecapiPayRefund;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import weixin.popular.api.PayMchAPI;
import weixin.popular.bean.paymch.SecapiPayRefundResult;
import weixin.popular.bean.paymch.Unifiedorder;
import weixin.popular.bean.paymch.UnifiedorderResult;
import weixin.popular.util.XMLConverUtil;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;

/**
 * 微信支付服务实现
 * 提供微信扫码支付、退款等相关功能
 *
 * @author houyong
 */
@Service
@RefreshScope
public class WxPayService extends AbstractPayService {
    private static final Logger logger = Logger.getLogger(WxPayService.class.getName());

    /**
     * 微信原生支付 appid
     */
    @Value("${weixin.native.appid}")
    public String wxNativeAppId;

    /**
     * 微信原生支付  商户号的秘钥
     */
    @Value("${weixin.native.mchkey}")
    public String wxNativeMchKey;//wxNativeMchKey

    /**
     * 微信原生支付  商户号
     */
    @Value("${weixin.native.mchid}")
    public String wxNativeMchId;

    /**
     * 微信原生支付  支付成功的通知地址
     */
    @Value("${weixin.native.pay.success.notify.url}")
    public String wxNativePaySuccessNotifyUrl;

    /**
     * 获取商品标题。
     * 该方法用于从给定的字符串中提取商品标题，确保标题的长度不超过指定的最大长度。
     * 如果原始字符串的长度超过了最大长度，则通过截取前缀来缩短标题。
     *
     * @param body 原始字符串，可能包含商品标题。
     * @return 提取后的商品标题，保证长度不超过最大长度。
     */
    private String getGoodsTitle(String body) {
        // 定义最大标题长度为120个字节
        int maxLength = 120;
        byte[] bytes = body.getBytes();
        // 检查原始字符串的长度是否超过最大长度
        if (bytes.length > maxLength) {
            // 如果超过，截取前maxLength个字节作为标题
            // 截取前maxLength个字节，并转换回字符串
            String truncatedString = new String(bytes, 0, maxLength);
            // 返回截取后的字符串
            return truncatedString;
        } else {
            return body;
        }
    }

    /**
     * 为扫码支付生成支付链接。
     *
     * @param order    订单信息，包含订单详情和支付金额等。
     * @param remoteIp 用户的IP地址，用于支付过程中进行地理定位。
     * @return 返回生成的支付二维码链接，如果生成失败则返回null。
     */
    public String generateChargeForScanQrCode(UserOrder order, String remoteIp) {
        // 创建统一订单对象
        Unifiedorder unifiedorder = new Unifiedorder();
        // 设置微信支付相关的应用ID和商户号
        unifiedorder.setAppid(wxNativeAppId);
        unifiedorder.setMch_id(wxNativeMchId);
        // 生成唯一的随机字符串，用于签名
        unifiedorder.setNonce_str(UUID.randomUUID().toString().replace("-", ""));
        // 设置订单描述、订单号和支付金额
        unifiedorder.setBody(getGoodsTitle(order.getBody()));
        unifiedorder.setOut_trade_no(order.getOrderId());
        unifiedorder.setTotal_fee(String.valueOf(order.getNeedPayFee()));//单位分
        // 设置用户的IP地址
        unifiedorder.setSpbill_create_ip(remoteIp);
        // 设置支付成功后的通知URL
        unifiedorder.setNotify_url(wxNativePaySuccessNotifyUrl);
        // 设置支付方式为扫码支付
        unifiedorder.setTrade_type("NATIVE");//JSAPI，NATIVE，APP，MWEB
        // 调用微信支付API，生成预支付订单
        UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, wxNativeMchKey);
        // 记录生成的预支付订单信息
        logger.info("系统订单：" + JSON.toJSONString(unifiedorderResult));
        // 检查预支付订单的签名状态，如果有效则返回二维码链接
        if (unifiedorderResult.getSign_status()) {
            return unifiedorderResult.getCode_url();
        }
        // 如果签名无效或其他错误，返回null
        return null;
    }

    /**
     * 微信体系 通过第三方SDK退款总接口
     *
     * @param appid            应用ID
     * @param mchid            商户ID
     * @param mchKey           商户密钥
     * @param refundAmount     退款金额(分)
     * @param orderTotalAmount 订单总金额(分)
     * @param refundId         退款订单ID
     * @param refundOrderId    原始订单ID
     * @param refundDesc       退款描述
     * @param notifyUrl        退款结果通知URL
     * @return 退款结果
     */
    public Map<String, String> wxRefund(String appid, String mchid, String mchKey,
                                        Integer refundAmount, Integer orderTotalAmount, String refundId,
                                        String refundOrderId, String refundDesc, String notifyUrl) {
        Map<String, String> map = new HashMap<>();
        try {
            JgrmSecapiPayRefund secapiPayRefund = new JgrmSecapiPayRefund();
            secapiPayRefund.setMch_id(mchid);
            secapiPayRefund.setAppid(appid);
            secapiPayRefund.setNonce_str(UUID.randomUUID().toString().replace("-", ""));
            secapiPayRefund.setOut_refund_no(refundId); //商户退款订单号
            secapiPayRefund.setOut_trade_no(refundOrderId);//商户订单号
            secapiPayRefund.setRefund_fee(refundAmount);//单位:分
            secapiPayRefund.setTotal_fee(orderTotalAmount);
            secapiPayRefund.setRefund_desc(refundDesc);
            secapiPayRefund.setNotify_url(notifyUrl);
            SecapiPayRefundResult secapiPayRefundResult = PayMchAPI.secapiPayRefund(secapiPayRefund, mchKey);
            String s = XMLConverUtil.convertToXML(secapiPayRefundResult);
            map = XMLConverUtil.convertToMap(s);
            logger.info(JSON.toJSONString(secapiPayRefundResult));
            return map;
        } catch (Exception e) {
            logger.severe("微信退款异常: " + e.getMessage());
            e.printStackTrace();
        }
        return map;
    }
}